#include "connection.h"
#include <iostream>
#include <thread>
#include "message_processor.h"

extern MessageProcessor message_processor;

Connection::Connection(boost::asio::io_context& io_context) : socket_(io_context), msg_length_(0) {}

Connection::~Connection() = default;

boost::asio::ip::tcp::socket& Connection::socket() {
    return socket_;
}

void Connection::start() {
    read_length();
}

void Connection::stop() {
    socket_.close();
}

void Connection::reconnect() {
    if (is_reconnecting_) return;
    is_reconnecting_ = true;
    reconnect_start_time_ = std::chrono::steady_clock::now();
    std::thread([this]() {
        while (is_reconnecting_) {
            try {
                socket_.close();
                socket_.connect(boost::asio::ip::tcp::endpoint(boost::asio::ip::make_address("127.0.0.1"), 12345));
                is_reconnecting_ = false;
                start();
                break;
            } catch (const std::exception& e) {
                auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - reconnect_start_time_).count();
                if (elapsed > 30) {
                    is_reconnecting_ = false;
                    break;
                }
                std::this_thread::sleep_for(std::chrono::seconds(5));
            }
        }
    }).detach();
}

void Connection::send(const google::protobuf::Message& msg) {
    uint32_t length = htonl(static_cast<uint32_t>(msg.ByteSizeLong()));
    std::string data(reinterpret_cast<const char*>(&length), sizeof(uint32_t));
    std::string proto_data;
    msg.SerializeToString(&proto_data);
    data.append(proto_data);
    write(data);
}

void Connection::read_length() {
    auto self(shared_from_this());
    boost::asio::async_read(socket_, boost::asio::buffer(&msg_length_, sizeof(uint32_t)),
                            [this, self](const boost::system::error_code& error, size_t length) {
                                if (!error) {
                                    msg_length_ = ntohl(msg_length_);
                                    buffer_.reset(new char[msg_length_]);
                                    read_proto_msg();
                                } else {
                                    if (error != boost::asio::error::eof) {
                                        reconnect();
                                    }
                                    stop();
                                }
                                std::cout << "length: " << length << std::endl;
                            });
}

void Connection::read_proto_msg() {
    auto self(shared_from_this());
    boost::asio::async_read(socket_, boost::asio::buffer(buffer_.get(), msg_length_),
                            [this, self](const boost::system::error_code& error, size_t length) {
                                if (!error) {
                                    // 这里可以将接收到的消息传递给上层处理
                                    std::string msg_str(buffer_.get(), msg_length_);
                                    // 示例处理，实际应根据消息类型分发
                                    std::cout << "Received message: " << msg_str << std::endl;
                                    uint32_t msg_type = 1; // 假设消息类型为1
                                    message_processor.process(buffer_.get(), length, msg_type, self);
                                } else {
                                    if (error != boost::asio::error::eof) {
                                        reconnect();
                                    }
                                    stop();
                                }
                                read_length();
                                std::cout << "length: " << length << std::endl;
                            });
}

void Connection::write(const std::string& data) {
    auto self(shared_from_this());
    boost::asio::async_write(socket_, boost::asio::buffer(data),
                             [this, self](const boost::system::error_code& error, std::size_t length) {
                                 if (!error) {
                                     handle_write(error);
                                     std::cout << "length: " << length << std::endl;
                                 } else {
                                     if (error != boost::asio::error::eof) {
                                         reconnect();
                                     }
                                     stop();
                                 }
                                 std::cout << "length: " << length << std::endl;
                             });
}

void Connection::handle_read(const boost::system::error_code& error, size_t length) {
    if (!error) {
        // 处理读取到的消息
    }
    read_length();
    std::cout << "length: " << length << std::endl;
}

void Connection::handle_write(const boost::system::error_code& error) {
    if (!error) {
        // 处理写入结果
    }
}